package com.maodou.core.navigation

import android.util.Log
import android.widget.Toast
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.maodou.core.R
import com.maodou.core.ui.components.AppLoadingOverlay
// 弹框容器（居中/底部/顶部）
import com.maodou.core.ui.components.BottomPopup
import com.maodou.core.ui.components.CenterPopup
import com.maodou.core.ui.components.HSpacer
import com.maodou.core.ui.components.PromptDialog
import com.maodou.core.ui.components.TopPopup
import com.maodou.core.ui.components.VSpacer
import com.maodou.core.utils.Logger
import com.maodou.core.utils.longToastOnUi
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

// 弹框样式（自定义内容时生效）
enum class DialogStyle { Center, Bottom, Top }

// 对话框句柄（可主动关闭）
interface DialogHandle { fun close() }

// 全局 UI 事件
sealed class GlobalUiEvent {
    data class ShowToast(val message: String, val long: Boolean = false) : GlobalUiEvent()
    data class ShowError(val message: String) : GlobalUiEvent()
    data class ShowSnackbar(
        val message: String,
        val actionLabel: String? = null,
        val withDismissAction: Boolean = false,
        val duration: SnackbarDuration = SnackbarDuration.Short,
        val onAction: (() -> Unit)? = null,
    ) : GlobalUiEvent()
    data class ShowLoading(val message: String? = null) : GlobalUiEvent()
    data object HideLoading : GlobalUiEvent()

    // 统一的弹出事件：可用于 Alert（传 message/title）或 Popup（传 content + style）
    data class ShowDialog(
        val title: String? = null,
        val message: String? = null,
        val positiveText: String = "确定",
        val negativeText: String? = null,
        val onConfirm: (() -> Unit)? = null,
        val onCancel: (() -> Unit)? = null,
        val content: (@Composable (() -> Unit))? = null,
        val style: DialogStyle = DialogStyle.Center,
        val dialogId: Long = System.nanoTime(),
        val cancelable: Boolean = true,
        val dismissOnClickOutside: Boolean = true,
        val dismissOnBackPress: Boolean = true,
    ) : GlobalUiEvent()

    data class HideDialogById(val id: Long) : GlobalUiEvent()
    data object HideAllDialogs : GlobalUiEvent()
    // 任务进度（用于顶部“灵动岛”展示）
    data class ShowTaskProgress(
        val taskId: Long,
        val title: String,
        val total: Int,
        val current: Int = 0,
    ) : GlobalUiEvent()
    data class UpdateTaskProgress(val taskId: Long, val current: Int) : GlobalUiEvent()
    data class HideTaskProgress(val taskId: Long) : GlobalUiEvent()
}

interface GlobalUiController {
    fun showToast(message: String, long: Boolean = true)
    fun showError(message: String)
    fun showSnackbar(
        message: String,
        actionLabel: String? = null,
        duration: SnackbarDuration = SnackbarDuration.Short,
        withDismissAction: Boolean = false,
        onAction: (() -> Unit)? = null,
    )

    fun showLoading(message: String? = null)
    fun hideLoading()

    // 文本型 Alert Dialog（系统对话框）
    fun showAlertDialog(
        title: String? = null,
        message: String? = null,
        positiveText: String = "确定",
        negativeText: String? = null,
        onConfirm: (() -> Unit)? = null,
        onCancel: (() -> Unit)? = null,
        cancelable: Boolean = true,
    ): DialogHandle

    // 自定义内容弹出（支持居中/底部/顶部）
    fun showPopup(
        content: @Composable () -> Unit,
        style: DialogStyle = DialogStyle.Center,
        dismissOnClickOutside: Boolean = true,
        dismissOnBackPress: Boolean = true,
        onDismiss: (() -> Unit)? = null,
    ): DialogHandle

    fun dismissDialogById(id: Long)
    fun dismissAllDialogs()

    // 顶部任务进度（灵动岛）
    fun showTaskProgress(taskId: Long, title: String, total: Int, current: Int = 0)
    fun updateTaskProgress(taskId: Long, current: Int)
    fun hideTaskProgress(taskId: Long)
}

object GlobalUiBus : GlobalUiController {
    val events = MutableSharedFlow<GlobalUiEvent>(extraBufferCapacity = 64, onBufferOverflow = BufferOverflow.DROP_OLDEST)

    override fun showToast(message: String, long: Boolean) {
        events.tryEmit(GlobalUiEvent.ShowToast(message, long))
    }

    override fun showError(message: String) {
        events.tryEmit(GlobalUiEvent.ShowError(message))
    }

    override fun showSnackbar(
        message: String,
        actionLabel: String?,
        duration: SnackbarDuration,
        withDismissAction: Boolean,
        onAction: (() -> Unit)?,
    ) {
        events.tryEmit(
            GlobalUiEvent.ShowSnackbar(
                message = message,
                actionLabel = actionLabel,
                withDismissAction = withDismissAction,
                duration = duration,
                onAction = onAction,
            )
        )
    }

    override fun showLoading(message: String?) {
        events.tryEmit(GlobalUiEvent.ShowLoading(message))
    }

    override fun hideLoading() {
        events.tryEmit(GlobalUiEvent.HideLoading)
    }

    override fun showAlertDialog(
        title: String?,
        message: String?,
        positiveText: String,
        negativeText: String?,
        onConfirm: (() -> Unit)?,
        onCancel: (() -> Unit)?,
        cancelable: Boolean,
    ): DialogHandle {
        val id = System.nanoTime()
        events.tryEmit(
            GlobalUiEvent.ShowDialog(
                title = title,
                message = message,
                positiveText = positiveText,
                negativeText = negativeText,
                onConfirm = onConfirm,
                onCancel = onCancel,
                content = null,
                style = DialogStyle.Center,
                dialogId = id,
                cancelable = cancelable,
                dismissOnClickOutside = true,
                dismissOnBackPress = true,
            )
        )
        return object : DialogHandle {
            override fun close() {
                events.tryEmit(GlobalUiEvent.HideDialogById(id))
            }
        }
    }

    override fun showPopup(
        content: @Composable () -> Unit,
        style: DialogStyle,
        dismissOnClickOutside: Boolean,
        dismissOnBackPress: Boolean,
        onDismiss: (() -> Unit)?,
    ): DialogHandle {
        val id = System.nanoTime()
        events.tryEmit(
            GlobalUiEvent.ShowDialog(
                title = null,
                message = null,
                positiveText = "",
                negativeText = null,
                onConfirm = null,
                onCancel = onDismiss,
                content = content,
                style = style,
                dialogId = id,
                cancelable = true,
                dismissOnClickOutside = dismissOnClickOutside,
                dismissOnBackPress = dismissOnBackPress,
            )
        )
        return object : DialogHandle {
            override fun close() {
                events.tryEmit(GlobalUiEvent.HideDialogById(id))
            }
        }
    }

    override fun dismissDialogById(id: Long) {
        events.tryEmit(GlobalUiEvent.HideDialogById(id))
    }

    override fun dismissAllDialogs() {
        events.tryEmit(GlobalUiEvent.HideAllDialogs)
    }

    override fun showTaskProgress(taskId: Long, title: String, total: Int, current: Int) {
        events.tryEmit(GlobalUiEvent.ShowTaskProgress(taskId, title, total, current))
    }

    override fun updateTaskProgress(taskId: Long, current: Int) {
        events.tryEmit(GlobalUiEvent.UpdateTaskProgress(taskId, current))
    }

    override fun hideTaskProgress(taskId: Long) {
        events.tryEmit(GlobalUiEvent.HideTaskProgress(taskId))
    }
}

val LocalGlobalUiController = staticCompositionLocalOf<GlobalUiController> { GlobalUiBus }

val LocalDialogHandle = staticCompositionLocalOf<DialogHandle?> { null }

@Composable
fun GlobalUiLayer(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    val context = LocalContext.current
    val scope = rememberCoroutineScope()
    val snackbarHostState = remember { SnackbarHostState() }
    val isLoading: MutableState<Boolean> = remember { mutableStateOf(false) }
    val loadingMessage: MutableState<String?> = remember { mutableStateOf(null) }
    val dialogsState: MutableState<List<GlobalUiEvent.ShowDialog>> = remember { mutableStateOf(emptyList()) }

    // 顶部任务进度（灵动岛）
    val taskProgressState: MutableState<GlobalUiEvent.ShowTaskProgress?> = remember { mutableStateOf(null) }

    LaunchedEffect(Unit) {
        GlobalUiBus.events.collectLatest { event ->
            when (event) {
                is GlobalUiEvent.ShowToast -> {
                    context.longToastOnUi(event.message)
                }
                is GlobalUiEvent.ShowError -> {
                    context.longToastOnUi(event.message)
                }
                is GlobalUiEvent.ShowSnackbar -> {
                    scope.launch {
                        val result = snackbarHostState.showSnackbar(
                            message = event.message,
                            actionLabel = event.actionLabel,
                            withDismissAction = event.withDismissAction,
                            duration = event.duration,
                        )
                        if (result == SnackbarResult.ActionPerformed) {
                            event.onAction?.invoke()
                        }
                    }
                }
                is GlobalUiEvent.ShowLoading -> {
                    isLoading.value = true
                    loadingMessage.value = event.message
                }
                is GlobalUiEvent.HideLoading -> {
                    isLoading.value = false
                    loadingMessage.value = null
                }
                is GlobalUiEvent.ShowDialog -> {
                    dialogsState.value += event
                }
                is GlobalUiEvent.HideDialogById -> {
                    dialogsState.value = dialogsState.value.filterNot { it.dialogId == event.id }
                }
                is GlobalUiEvent.HideAllDialogs -> {
                    dialogsState.value = emptyList()
                }
                is GlobalUiEvent.ShowTaskProgress -> {
                    taskProgressState.value = event
                }
                is GlobalUiEvent.UpdateTaskProgress -> {
                    val cur = taskProgressState.value
                    if (cur != null && cur.taskId == event.taskId) {
                        taskProgressState.value = cur.copy(current = event.current)
                    }
                }
                is GlobalUiEvent.HideTaskProgress -> {
                    val cur = taskProgressState.value
                    if (cur != null && cur.taskId == event.taskId) {
                        taskProgressState.value = null
                    }
                }
            }
        }
    }

    Box(modifier = modifier.fillMaxSize()) {
        content()
        SnackbarHost(hostState = snackbarHostState, modifier = Modifier.align(Alignment.TopCenter))
        if (isLoading.value) {
            AppLoadingOverlay(
                text =  loadingMessage.value ?: "数据加载中...",
                visible = isLoading.value,
                iconRes = R.mipmap.ic_loading_white,
                scrimColor = MaterialTheme.colorScheme.scrim.copy(alpha = 0f)
            )
        }

        // 顶部“灵动岛”任务进度
        val tp = taskProgressState.value
        if (tp != null) {
            val infinite = rememberInfiniteTransition(label = "loading-rotation")
            val angle by infinite.animateFloat(
                initialValue = 0f,
                targetValue = 360f,
                animationSpec = infiniteRepeatable(
                    animation = tween(durationMillis = 1200, easing = LinearEasing)
                ),
                label = "angle"
            )
            Box(
                modifier = Modifier
                    .align(Alignment.TopCenter)
                    .padding(top = 8.dp)
                    .background(
                        color = Color.Black.copy(alpha = 0.95f),
                        shape = RoundedCornerShape(50.dp)
                    ).width(156.dp).padding(horizontal = 12.dp, vertical = 6.dp)
            ) {
                Column(horizontalAlignment = Alignment.CenterHorizontally) {
                    Row(verticalAlignment = Alignment.CenterVertically) {
                        Image(
                            painter = painterResource(id = R.mipmap.ic_loading_white),
                            contentDescription = null,
                            modifier = Modifier
                                .size(12.dp)
                                .rotate(-angle)
                        )
                        HSpacer(4.dp)
                        Text(
                            text = tp.title,
                            style = MaterialTheme.typography.bodySmall.copy(fontSize = 12.sp),
                            color = Color.White,
                            overflow = TextOverflow.Ellipsis,
                            maxLines = 1
                        )
                    }
                    VSpacer(4.dp)
                    val progress = if (tp.total <= 0) 0f else tp.current.coerceAtMost(tp.total).toFloat() / tp.total.toFloat()
                    LinearProgressIndicator(
                        progress = { progress },
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(3.dp).padding(horizontal = 4.dp),
                        color = Color.White,
                        trackColor = Color.Transparent,
                    )
                }
            }
        }

        val current = dialogsState.value.lastOrNull()
        if (current != null) {
            // 自定义内容 + 无 message 时走动画弹框容器
            if (current.content != null && current.message.isNullOrEmpty()) {
                val onDismiss = {
                    current.onCancel?.invoke()
                    dialogsState.value = dialogsState.value.dropLast(1)
                }
                val handle = remember(current.dialogId) {
                    object : DialogHandle {
                        override fun close() {
                            GlobalUiBus.events.tryEmit(GlobalUiEvent.HideDialogById(current.dialogId))
                        }
                    }
                }
                when (current.style) {
                    DialogStyle.Center -> {
                        CenterPopup(
                            visible = true,
                            onDismissRequest = onDismiss,
                            dismissOnClickOutside = current.dismissOnClickOutside,
                            dismissOnBackPress = current.dismissOnBackPress,
                        ) {
                            androidx.compose.runtime.CompositionLocalProvider(LocalDialogHandle provides handle) {
                                current.content.invoke()
                            }
                        }
                    }
                    DialogStyle.Bottom -> {
                        BottomPopup(
                            visible = true,
                            onDismissRequest = onDismiss,
                            dismissOnClickOutside = current.dismissOnClickOutside,
                            dismissOnBackPress = current.dismissOnBackPress,
                        ) {
                            androidx.compose.runtime.CompositionLocalProvider(LocalDialogHandle provides handle) {
                                current.content.invoke()
                            }
                        }
                    }
                    DialogStyle.Top -> {
                        TopPopup(
                            visible = true,
                            onDismissRequest = onDismiss,
                            dismissOnClickOutside = current.dismissOnClickOutside,
                            dismissOnBackPress = current.dismissOnBackPress,
                        ) {
                            androidx.compose.runtime.CompositionLocalProvider(LocalDialogHandle provides handle) {
                                current.content.invoke()
                            }
                        }
                    }
                }
            } else {
                PromptDialog(
                    title = current.title ?: "${current.message}",
                    content = current.message,
                    okText = current.positiveText,
                    cancelText = current.negativeText ?: "取消",
                    okColor = MaterialTheme.colorScheme.primary,
                    onOk = {
                        current.onConfirm?.invoke()
                        dialogsState.value = dialogsState.value.dropLast(1)
                    },
                    onCancel = if (current.cancelable) {
                        {
                            current.onCancel?.invoke()
                            dialogsState.value = dialogsState.value.dropLast(1)
                        }
                    } else null,
                    onDismiss = {
                        if (current.cancelable) {
                            current.onCancel?.invoke()
                            dialogsState.value = dialogsState.value.dropLast(1)
                        }
                    }
                )

            }
        }
    }
}